package com.cqs.leetcode.design;

import java.util.*;

class Twitter {

    /**
     * ["Twitter","postTweet","getNewsFeed","follow","postTweet","getNewsFeed","unfollow","getNewsFeed"]
     * [[],[1,5],[1],[1,2],[2,6],[1],[1,2],[1]]
     * ["Twitter","postTweet","getNewsFeed","follow","getNewsFeed","unfollow","getNewsFeed"]
     * [[],[1,1],[1],[2,1],[2],[2,1],[2]]
     * ["Twitter","postTweet","follow","getNewsFeed"]
     * [[],[1,5],[1,1],[1]]
     */
    //消息计数器
    int cnt;

    class Message {
        int userId;
        int timestamp;
        int tweetId;
    }

    Map<Integer, List<Message>> tweetMap = new HashMap<>();
    //关注者列表
    Map<Integer, Set<Integer>> followees = new HashMap<>();

    /**
     * Initialize your data structure here.
     */
    public Twitter() {

    }

    /**
     * Compose a new tweet.
     */
    public void postTweet(int userId, int tweetId) {
        List<Message> queue = tweetMap.computeIfAbsent(userId, k -> new LinkedList<>());
        Message message = new Message();
        message.userId = userId;
        message.timestamp = ++cnt;
        message.tweetId = tweetId;
        queue.add(0,message);
    }

    /**
     * Retrieve the 10 most recent tweet ids in the user's news feed. Each item in the news feed must be posted by users who the user followed or by the user herself. Tweets must be ordered from most recent to least recent.
     */
    public List<Integer> getNewsFeed(int userId) {
        PriorityQueue<Message> queue = new PriorityQueue<>(10, Comparator.comparingInt(o -> o.timestamp));
        List<Message> queue1 = tweetMap.get(userId);
        if (queue1 != null) {
            Iterator<Message> iterator = queue1.iterator();
            //自己的队列是有先后顺序的
            while (iterator.hasNext() && queue.size() < 10) {
                queue.add(iterator.next());
            }
        }
        //关注的人列表
        Set<Integer> fs = followees.get(userId);
        if (fs != null) {
            for (Integer followee : fs) {
                List<Message> q = tweetMap.get(followee);
                if (q == null) continue;
                Iterator<Message> iterator = q.iterator();
                while (iterator.hasNext()) {
                    Message next = iterator.next();
                    if (queue.size() < 10) {
                        queue.add(next);
                    } else if (next.timestamp > queue.peek().timestamp) {
                        //替换
                        queue.poll();
                        queue.add(next);
                    } else {
                        break;
                    }
                }
            }
        }
        List<Integer> result = new ArrayList<>(queue.size());
        while (queue.size() > 0) {
            //最小的
            Message poll = queue.poll();
            //从后向前插入
            result.add(0, poll.tweetId);
        }
        return result;
    }

    /**
     * Follower follows a followee. If the operation is invalid, it should be a no-op.
     */
    public void follow(int followerId, int followeeId) {
        if (followerId == followeeId) return;
        Set<Integer> set = followees.computeIfAbsent(followerId, k -> new HashSet<>());
        set.add(followeeId);
    }

    /**
     * Follower unfollows a followee. If the operation is invalid, it should be a no-op.
     */
    public void unfollow(int followerId, int followeeId) {
        if (followerId == followeeId) return;
        Set<Integer> set = followees.get(followerId);
        if (set != null) {
            set.remove(followeeId);
        }
    }
}


/**
 * Your Twitter object will be instantiated and called as such:
 * Twitter obj = new Twitter();
 * obj.postTweet(userId,tweetId);
 * List<Integer> param_2 = obj.getNewsFeed(userId);
 * obj.follow(followerId,followeeId);
 * obj.unfollow(followerId,followeeId);
 */

